package eu.jk.config;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.LinkedList;
import java.util.List;

final class PathResolver {

	static class Token {

		public final int type;

		public String token;

		public Token(int type, String token) {
			this.type = type;
			this.token = token;
		}

		interface TYPE {
			int PATH_NAME = 0;

			int VALUE_NAME = 1;

			int EXPRESS_LEFT = 2;

			int EXPRESS_RIGHT = 3;
		}
	}

	private List<Token> tokens = null;

	private int pointer = -1;
	
	public void resolve(String path) {
		tokens = new LinkedList<PathResolver.Token>();
		Reader reader = new StringReader(path);
		int readLen = 0;
		char[] readBuf = new char[256];
		StringBuffer buffer = new StringBuffer();
		int state = STATE.INIT;
		try {
			while ((readLen = reader.read(readBuf)) > 0) {
				for (int index = 0; index < readLen; index++) {
					char c = readBuf[index];
					switch (state) {
					case STATE.INIT:
						state = doInitState(c, buffer);
						break;
					case STATE.PATH:
						state = doPathState(c, buffer);
						break;
					case STATE.EXPRESS_LEFT:
						state = doExpressLeftState(c, buffer);
						break;
					case STATE.EXPRESS_RIGHT:
						state = doExpressRightState(c, buffer);
						break;
					}
				}
			}
			flushToken(buffer, Token.TYPE.VALUE_NAME);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	interface STATE {
		int INIT = 0;

		int PATH = 1;

		int EXPRESS_LEFT = 2;

		int EXPRESS_RIGHT = 3;
	}

	public int doInitState(char currentChar, StringBuffer buffer) {
		switch (currentChar) {
		case '/':
			return STATE.PATH;
		}
		return STATE.PATH;
	}

	public int doPathState(char currentChar, StringBuffer buffer) {
		switch (currentChar) {
		case '/':
			flushToken(buffer, Token.TYPE.PATH_NAME);
			break;
		case '[':
			flushToken(buffer, Token.TYPE.PATH_NAME);
			return STATE.EXPRESS_LEFT;
		default:
			buffer.append(currentChar);
		}
		return STATE.PATH;
	}

	public int doExpressLeftState(char currentChar, StringBuffer buffer) {
		switch (currentChar) {
		case '=':
			flushToken(buffer, Token.TYPE.EXPRESS_LEFT);
			return STATE.EXPRESS_RIGHT;
		default:
			buffer.append(currentChar);
		}
		return STATE.EXPRESS_LEFT;
	}

	public int doExpressRightState(char currentChar, StringBuffer buffer) {
		switch (currentChar) {
		case ']':
			flushToken(buffer, Token.TYPE.EXPRESS_RIGHT);
			return STATE.INIT;
		default:
			buffer.append(currentChar);
		}
		return STATE.EXPRESS_RIGHT;
	}

	private void flushToken(StringBuffer buffer, int type) {
		if (buffer.length() == 0)
			return;
		tokens.add(new Token(type, buffer.toString()));
		buffer.delete(0, buffer.length());
	}

	public boolean next() {
		if (++pointer >= tokens.size())
			return false;
		return true;
	}
	
	public Token getToken() {
		return tokens.get(pointer);
	}

	public void reset() {
		pointer = -1;
	}
}
